Modify existing code for link-by-attr. Looking for a undo/restore script.

Hello,

I found the following code on www.smartdxl.com and was wondering what would be needed to modify this code to also do in-links so that this can be a one stop script to restore a module's links that was restored from an backup/archive. I was also was wondering if anyone has a script that would restore/undo changes to a Module? (I am looking for a cript that would undo change made on a certain date and by a certain user)

Thank you,
Jim

saveLinks.dxl :

// So here is the script to save ur links in an attribute ... 
// Just put an attribute name in the ... linkAttribute variable 
// and run the script ;) 
 
// link attribute name definition 
// here u put the attribute name that u want ;) 
// i've choosen "Save" for example ... 
const string linkAttribute = "Save" 
const string moduleLinkAttribute = linkAttribute "_module" 
 
// U need to have write access on the current module ... 
if ( ! canModify ( current Module ) ) { 
   print "U need write access on the current module to save the links as an attribute" 
   halt 
} 
// create the attribute ( only if it doesn't exist ... ) 
if ( null find ( current Module, linkAttribute"" ) ) { 
   create object type "String" attribute linkAttribute"" 
} 
// create a module atrtibute to store the target module list ... 
if ( null find ( current Module, linkAttribute "_module" ) ){ 
   create module type "String" attribute (linkAttribute "_module") 
} 
//save current Module // u can comment this line ;) 
 
// I - loop on the module ... searching all objects with links 
// and translate the links attribute's values ;) 
// 
Module       m                = current Module 
Object       o 
Link       l 
ModName_    target_module 
Object       target_object 
Module       temp_mod 
Skip       target_module_list    = create    // data structure to store the targets modules 
 
// I - open all targets modules and store the links in an attribute 
 
// I.1 - open all the targets modules ;) 
// I assume u have read wright on each of them ... no more test here o:) 
for o in m do {       // beware, i don't check the filter to allow u to 
   for l in o->"*" do {         // save only the links that u need ... but that's means 
      target_module = target l   // u have to be carrefull and don't forget any ;) 
      temp_mod = read ( fullName target_module, false ) 
      put ( target_module_list, temp_mod, temp_mod ) 
   } 
} 
// targets modules are readables, we can now access the targets objects ... :) 
 
// I.2 - store the target modules list in the module attribute 
string tmp="" 
for temp_mod in target_module_list do { 
   if ( tmp"" == "" ) tmp = fullName temp_mod 
   else tmp = tmp "\n" fullName temp_mod 
} 
m.moduleLinkAttribute = tmp"" 
 
// I.3 - loop on the links of each objects ... 
tmp = "" 
for o in m do {                     // loop on module's objects 
   for l in o->"*" do {            // loop on link's objects 
      target_module = target l 
      if ( tmp"" == "" ) { tmp = fullName target_module } 
      else { tmp = tmp "\n" fullName target_module } 
      target_object = target l 
      tmp = tmp ";" target_object."absolute number""" 
   } 
   o.linkAttribute = tmp"" 
   tmp = "" 
} 
 
// II - Clean the memory ... 
 
// II.1 - close the targets modules 
for temp_mod in target_module_list do { close temp_mod } 
 
// II.2 - explicit memeory free ;) 
delete target_module_list

 


restoreLinks.dxl :

 

 

// Restore links using attribute values. 
// Format data expected : full path of target module;absolute number of target object 
//             ... 
 
// No test done with module links ... 
// U have to use the linkset mecanism to ensure the right use of 
// ur links modules 
 
// tool 
// split function ... 
// give u a skip list of all lines of a string ;) 
Skip split ( string s ) {    
   Skip split_string = create 
   int deb = 0; int i; int index = 0 
   for ( i=0; i<length(s)-1; i++ ) { 
      if ( s[i] != '\n' ) continue 
      put( split_string, index, s[deb:i-1] ) 
      deb = i+1; index += 1 
   } 
   put ( split_string, s[deb:i], s[deb:i] ) 
   return split_string 
} 
 
// link attribute name definition 
// here u put the attribute name that u want ;) 
const string linkAttribute = "Save" 
const string moduleLinkAttribute = linkAttribute "_module" 
 
// 
 
Module m = current 
 
// // check if we can find the restoration needed attributes ... 
// // check the object attribute ( only if it doesn't exist ... ) 
// if ( null find ( m, linkAttribute"" ) ) { 
//    print "Can not find the object attribute " linkAttribute "\nHalt !"; halt 
// } 
// // check the module attribute ... 
// if ( null find ( m, moduleLinkAttribute""  ) ){ 
//    print "Can not find the module attribute " moduleLinkAttribute "\nHalt !"; halt 
// } 
// 
// Like in the saveLinks.dxl script, i begin to open all 
// the targets modules ... 
Object o 
Skip target_module_name_list = split (m.moduleLinkAttribute"") 
Skip target_module_list = create // anticipate the closing target module step ;) 
string tmp = "" 
Module tmp_mod 
for tmp in target_module_name_list do { 
   tmp_mod = read(tmp, false) // i assume u have the read wrigths ... no more test here 
   put ( target_module_list, tmp, tmp_mod ) 
} 
// i free the memory as soon as possible, like usual ;) 
delete target_module_name_list 
 
// restore the links ... 
Skip link_list 
int i 
string target_module_name 
string target_object_abs_number 
Object target_obj 
for o in m do { // loop on the module 
   if ( o.linkAttribute"" == "" ) continue 
   link_list = split ( o.linkAttribute"" ) 
   for tmp in link_list do { // loop on the values of the attribute to restore 
      for( i=0; i<length(tmp); i++ ) if ( tmp[i] == ';' ) break 
      target_module_name = tmp[0:i-1]   // no test, in storeLinks script we trust ;) 
      target_object_abs_number = tmp[i+1:] 
      find ( target_module_list, target_module_name, tmp_mod ) // target module found 
      target_obj = object ( intOf target_object_abs_number, tmp_mod ) // target_obj found ;) 
      o->target_obj // using linkset mecanism to ensure the right link module use ... 
   } 
   delete link_list 
} 
 
for tmp_mod in target_module_list do { 
   close tmp_mod 
} 
 
delete target_module_list

 


SystemAdmin - Tue Oct 18 00:43:38 EDT 2011

Re: Modify existing code for link-by-attr. Looking for a undo/restore script.
llandale - Tue Oct 18 09:56:27 EDT 2011

Thoughts on a script to restore changes made my individual users:
<1> Specify the date range
Present a list of Sessions in some kind of list view
Perhaps present a list of object Sections for consideration, or just certain attributes (e.g. revert Object Heading and Text changes in section 3.1 only).
For History in that session, accumulate all the changes for a particular obj-attr value resulting in a 'changes' list featuring an "old" value from the 1st such History and a "new" value from the last such History.
For History in that Session, do NOT revert if the current obj-attr value is not the same as the "new" value in the History. However, there will be exceptions to this that will prove hard to handle.
I think you will end up with a pile of "auto-reverts" which are simple (such as there exists only one such History), and a separate pile of "confirm-reverts" which are complicated (more than one History by more than one person) and presented individually to the user to confirm or cancel. This confirm will want to show recent History for that obj-attr value so the user can make a mindful choice.

This may get rather complicated if you revert Joe's session #3 on Tuesday, and later then try to revert Joe's session #7 on Thursday or Mary's session #6 on Wednesday. You may want to have a special user named 'Revert' so your revert program can know to ignore reverts by Revert; or know to search for a "current" value that existed before Revert did some other Revert.

Thoughts on the below script:
These are Save/Restore OutLinks scripts.
May want to rename the attribute to "Save-OutLinks" and "Save-InLinks".
You could copy them to make Save/Restore InLinks scripts.
Seems pretty straight forward to modify the InLink script to first loop through LinkRefs and open up the Source module, Read for Save-InLinks.dxl and Edit for Restore-InLinks.dxl. The module-level attribute doesn't seem to server a purpose, and in any event can be the same attribute as the Object level one.
Attributes will need to be type "text" not "string" or the 964 character limit on String attributes won't be enough for objects with lots of links.
I have doubts about this script's ability to create the links in the correct link module.
the "for o in mod" loops are inadequate; need "for o in entire mod" loop; otherwise you are subject to the filter in the default view.
using function "object(AbsNo)" to search for objects is inadequate; ditto due to the default view.
Needs to use a Buffer to accumulate save-attr-values
Function 'split' has rather serious bug,
change .. put ( split_string, sdeb:i, sdeb:i )
to ..... put ( split_string, index, sdeb:i )
As do most linking scripts (including all of mine), this script fails to take into account versioned links to baselines.

The one I wrote so many long years ago created a separate attribute for each separate link-set, putting the linkmod and target/source mod name in the name of the attribute, leaving the object-attr values as a straight list of absolute numbers. I think that's better than this but certainly could be approved.

  • Louie